﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Xsl;
using System.Web;
using ConsoleXmlParser;

namespace _6.ParseSimplifiedTeamPulseFile
{
	public class ConsoleReleaseNotesParser
	{
		private const string XMLNS_PATTERN = "(xmlns=\")(.)+(\")";
		private const string XMLNS_REPLACEMENT = "";
		private const string TAG_PATTERN = @"(?<tag>(<.+?/?>))";
		private const string XML_FILE_HEADER = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
		private const string MESSAGE_FILE_DOESNT_EXIST = "The file you uploaded does NOT exist!";
		private const string MESSAGE_FILE_CANNOT_BE_LOADED = "The file you specified cannot be loaded!";
		private const string MESSAGE_XMLNS_CANNOT_BE_REMOVED = "There was a problem with removing the xmlns tag from the input file!";

		public static void Main()
		{
			//string filePathOriginalTeamPulseFile = "../../final-sorted-team-pulse.xml";
			string filePathOriginalTeamPulseFile = "../../real-team-pulse-file.xml";
			string filePathWithRemovedXmlns = "../../file-with-removed-xmlns.xml";
			string filePathSimplifiedTeamPulseFile = "../../Simplified-TeamPulse-File-2.xml";
			//string teamPulseFilePathWithRemovedXmlns = "../../team-pulse-file-removed-xmlns.xml";
			//string filePathLIBTransformationTemplate = "../../Latest-Internal-Build-Template.xsl";
			string filePathReleaseNotesTemplate = "../../Release-Notes-Template.xsl";
			//string filePathParsedHtml = "../../Parsed-TeamPulse-File.html";
			string filePathParsedHtml = "../../Release-Notes-Parsed-File.xml";

			try
			{
				CreateFileWithRemovedXmlns(filePathOriginalTeamPulseFile, filePathWithRemovedXmlns);
			}
			catch (Exception e)
			{
				Console.WriteLine(MESSAGE_XMLNS_CANNOT_BE_REMOVED + " " + e.Message);
			}

			try
			{
				//CreateSimplifiedTeamPulseFile(filePathWithRemovedXmlns, filePathSimplifiedTeamPulseFile);
				CreateSimplifiedTeamPulseFile(Constants.CSV_TEAMPULSE_FILE, filePathSimplifiedTeamPulseFile, true);
			}
			catch (Exception e)
			{
				Console.WriteLine("Cannot create file with simplified structure. " +
					"Check your input .xml file for correct document structure" + Environment.NewLine + e.Message);
			}


			XslCompiledTransform xsltParser = new XslCompiledTransform();
			try
			{
				xsltParser.Load(filePathReleaseNotesTemplate);
			}
			catch (Exception e)
			{
				Console.WriteLine(MESSAGE_FILE_CANNOT_BE_LOADED + Environment.NewLine + e.Message);
			}

			try
			{
				xsltParser.Transform(filePathSimplifiedTeamPulseFile, filePathParsedHtml);
			}
			catch (Exception e)
			{
				Console.WriteLine("Error when transforming the file with XSLT from " + filePathSimplifiedTeamPulseFile + " "
					+ Environment.NewLine + e.Message);
			}

			Console.WriteLine("The XML Document has been successfuly converted to HTML!");
		}

		public static void CreateSimplifiedTeamPulseFile(string filePathOriginalXmlFile, string filePathSimplifiedXmlFile, bool fromCSV = false)
		{
			if (fromCSV == true)
			{
				CSVParser csvParser = new CSVParser();
				csvParser.Parse(filePathOriginalXmlFile, filePathSimplifiedXmlFile);
			}
			else
			{
				if (!File.Exists(filePathOriginalXmlFile))
				{
					throw new FileNotFoundException(MESSAGE_FILE_DOESNT_EXIST);
				}

				XmlDocument xmlDocument = new XmlDocument();
				try
				{
					xmlDocument.Load(filePathOriginalXmlFile);
				}
				catch (Exception e)
				{
					Console.WriteLine(MESSAGE_FILE_CANNOT_BE_LOADED + Environment.NewLine + e.Message);
				}

				string xPathQueryMatchRows = "/Workbook/Worksheet/Table/Row";
				string xPathQueryMatchCells = "Cell";
				XmlNodeList rows = xmlDocument.SelectNodes(xPathQueryMatchRows);

				string previousControlName = null;
				using (StreamWriter writer = new StreamWriter(filePathSimplifiedXmlFile))
				{
					writer.WriteLine(XML_FILE_HEADER);
					writer.WriteLine("<controls>");
					writer.WriteLine("<control>");

					List<string> stories = new List<string>();
					List<string> bugs = new List<string>();

					foreach (XmlNode item in rows)
					{
						XmlNodeList cells = item.SelectNodes(xPathQueryMatchCells);

						string currentElementType = cells[0].InnerText;
						string currentElementText = cells[1].InnerText;
						string currentControlName = cells[2].InnerText;

						string controlNameWithRemovedBackSlashes = GetStrippedName(currentControlName);

						if (previousControlName != controlNameWithRemovedBackSlashes)
						{
							WriteStoriesAndBugs(writer, stories, bugs);
							previousControlName = controlNameWithRemovedBackSlashes;
							writer.WriteLine("<control>");
							string controlNameWithoutRadPrefix = controlNameWithRemovedBackSlashes.Replace("Rad", "");
							writer.WriteLine("<area>" + controlNameWithoutRadPrefix + "</area>");

						}
						AddStoryOrBug(stories, bugs, currentElementType, currentElementText);
					}

					WriteStoriesAndBugs(writer, stories, bugs);
					writer.WriteLine("</controls>");
				}
			}
			

		}



		private static void AddStoryOrBug(List<string> stories, List<string> bugs, string currentElementType, string currentElementText)
		{
			if (currentElementType == "Bug")
			{
				bugs.Add(currentElementText);
			}
			else
			{
				if (currentElementType == "Story")
				{
					stories.Add(currentElementText);
				}
			}
		}

		public static void CreateFileWithRemovedXmlns(string filePathOriginalXmlFile, string filePathRemovedXmlnsFile)
		{
			if (!File.Exists(filePathOriginalXmlFile))
			{
				throw new FileNotFoundException(MESSAGE_FILE_DOESNT_EXIST);
			}

			string textToFind = "xmlns=";

			using (StreamWriter writer = new StreamWriter(filePathRemovedXmlnsFile))
			{
				using (StreamReader reader = File.OpenText(filePathOriginalXmlFile))
				{
					bool isTextFound = false;
					int lineNumber = 0;
					string line = null;
					while ((line = reader.ReadLine()) != null)
					{
						lineNumber++;
						if (line.IndexOf(textToFind) > -1)
						{
							isTextFound = true;
							string replacedLine = Regex.Replace(line, XMLNS_PATTERN, XMLNS_REPLACEMENT);
							writer.WriteLine(replacedLine);
						}
						else
						{
							writer.WriteLine(line);
						}
					}
					if (!isTextFound)
					{
						Console.WriteLine("The text 'xmlns' wasn't found in the .xml file!");
					}
				}
			}
		}

		private static void WriteStoriesAndBugs(StreamWriter writer, List<string> stories, List<string> bugs)
		{
			if (stories.Count > 0)
			{
				writer.WriteLine("<stories>");
				for (int i = 0; i < stories.Count; i++)
				{
					//string replacedStoryText = stories[i].Replace("<p>&nbsp;</p>", "<p>nbsp;</p>");
					//string finalStoryText = GetTextWithoutTagBrackets(replacedStoryText);

					string finalStoryText = HttpUtility.HtmlEncode(stories[i]);
					writer.WriteLine("<story>" + finalStoryText + "</story>");

				}
				writer.WriteLine("</stories>");
			}
			stories.Clear();

			if (bugs.Count > 0)
			{
				writer.WriteLine("<bugs>");
				for (int i = 0; i < bugs.Count; i++)
				{
					//string replacedBugText = bugs[i].Replace("<p>&nbsp;</p>", "<p>nbsp;</p>");
					//string finalBugText = GetTextWithoutTagBrackets(replacedBugText);

					string finalBugText = HttpUtility.HtmlEncode(bugs[i]);

					writer.WriteLine("<bug>" + finalBugText + "</bug>");
				}
				writer.WriteLine("</bugs>");
			}
			bugs.Clear();

			writer.WriteLine("</control>");
		}

		private static string GetStrippedName(string controlName)
		{
			int firstBackSlashPosition = controlName.IndexOf("/");
			bool isStripped = false;
			string strippedName = null;
			if (firstBackSlashPosition > 0)
			{
				//Console.WriteLine(firstBackSlashPosition + " " + controlName[firstBackSlashPosition]);
				int secondBackSlashPosition = controlName.IndexOf("/", firstBackSlashPosition + 1);

				if (secondBackSlashPosition > 0)
				{
					//Console.WriteLine(secondBackSlashPosition + " " + controlName[secondBackSlashPosition]);
					strippedName = controlName.Substring(firstBackSlashPosition + 1, secondBackSlashPosition - 5).Trim();
				}
				else
				{
					strippedName = controlName.Substring(firstBackSlashPosition + 1).Trim();
				}
				//Console.WriteLine(strippedName + "END");
				isStripped = true;
			}

			if (isStripped == true)
			{
				return strippedName;
			}

			return controlName;
		}

		private static string GetTextWithoutTagBrackets(string text)
		{
			string copiedText = text;

			Match match = Regex.Match(text, TAG_PATTERN);

			//int i = 1;

			while (match.Success)
			{
				//Console.WriteLine("The tag starts at position {0}", match.Index);
				string tagText = match.Groups["tag"].Value;
				//string innerText = tagText.Substring(1, tagText.Length - 2);
				//copiedText = copiedText.Replace(tagText, innerText);

				////string decodedText = HttpUtility.HtmlDecode(tagText);
				//string encodedText = HttpUtility.HtmlEncode(tagText);



				//Console.WriteLine(copiedText);
				//Console.WriteLine(innerText);
				//Console.WriteLine("Founded text: {0}", tagText);
				//i++;
				match = match.NextMatch();
			}

			//Console.WriteLine("original text:" + text);
			//Console.WriteLine("final text:" + copiedText);
			return copiedText;
		}
	}
}
